home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / CONES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-25  |  18.1 KB  |  1,059 lines  |  [TEXT/CWIE]

  1. /****************************************************************************
  2. *                cones.c
  3. *
  4. *  This module implements the cone primitive.
  5. *  This file was written by Alexander Enzmann.    He wrote the code for
  6. *  cones and generously provided us these enhancements.
  7. *
  8. *  from Persistence of Vision(tm) Ray Tracer
  9. *  Copyright 1996 Persistence of Vision Team
  10. *---------------------------------------------------------------------------
  11. *  NOTICE: This source code file is provided so that users may experiment
  12. *  with enhancements to POV-Ray and to port the software to platforms other 
  13. *  than those supported by the POV-Ray Team.  There are strict rules under
  14. *  which you are permitted to use this file.  The rules are in the file
  15. *  named POVLEGAL.DOC which should be distributed with this file. If 
  16. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  18. *  Forum.  The latest version of POV-Ray may be found there as well.
  19. *
  20. * This program is based on the popular DKB raytracer version 2.12.
  21. * DKBTrace was originally written by David K. Buck.
  22. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  23. *
  24. *****************************************************************************/
  25.  
  26. #include "frame.h"
  27. #include "povray.h"
  28. #include "vector.h"
  29. #include "povproto.h"
  30. #include "bbox.h"
  31. #include "cones.h"
  32. #include "matrices.h"
  33. #include "objects.h"
  34.  
  35.  
  36.  
  37. /*****************************************************************************
  38. * Local preprocessor defines
  39. ******************************************************************************/
  40.  
  41. #define Cone_Tolerance 1.0e-6
  42.  
  43. #define close(x, y) (fabs(x-y) < EPSILON ? 1 : 0)
  44.  
  45. /* Part of the cone/cylinder hit. [DB 9/94] */
  46.  
  47. #define BASE_HIT 1
  48. #define CAP_HIT  2
  49. #define SIDE_HIT 3
  50.  
  51.  
  52.  
  53. /*****************************************************************************
  54. * Local typedefs
  55. ******************************************************************************/
  56.  
  57. typedef struct Cone_Intersection_Structure CONE_INT;
  58.  
  59. struct Cone_Intersection_Structure
  60. {
  61.   DBL d;  /* Distance of intersection point               */
  62.   int t;  /* Type of intersection: base/cap plane or side */
  63. };
  64.  
  65.  
  66.  
  67. /*****************************************************************************
  68. * Static functions
  69. ******************************************************************************/
  70.  
  71. static int intersect_cone PARAMS((RAY *Ray, CONE *Cone, CONE_INT *Depths));
  72. static void Destroy_Cone PARAMS((OBJECT *Object));
  73. static int All_Cone_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
  74. static int Inside_Cone PARAMS((VECTOR point, OBJECT *Object));
  75. static void Cone_Normal PARAMS((VECTOR Result, OBJECT *Object, INTERSECTION *Inter));
  76. static void *Copy_Cone PARAMS((OBJECT *Object));
  77. static void Translate_Cone PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  78. static void Rotate_Cone PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  79. static void Scale_Cone PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  80. static void Transform_Cone PARAMS((OBJECT *Object, TRANSFORM *Trans));
  81. static void Invert_Cone PARAMS((OBJECT *Object));
  82.  
  83.  
  84. /*****************************************************************************
  85. * Local variables
  86. ******************************************************************************/
  87.  
  88. static METHODS Cone_Methods =
  89. {
  90.   All_Cone_Intersections,
  91.   Inside_Cone, Cone_Normal,
  92.   Copy_Cone, Translate_Cone, Rotate_Cone, Scale_Cone, Transform_Cone,
  93.   Invert_Cone, Destroy_Cone
  94. };
  95.  
  96.  
  97.  
  98. /*****************************************************************************
  99. *
  100. * FUNCTION
  101. *
  102. *   All_Cone_Intersections
  103. *
  104. * INPUT
  105. *   
  106. * OUTPUT
  107. *   
  108. * RETURNS
  109. *   
  110. * AUTHOR
  111. *
  112. *   Alexander Enzmann
  113. *   
  114. * DESCRIPTION
  115. *
  116. *   -
  117. *
  118. * CHANGES
  119. *
  120. *   -
  121. *
  122. ******************************************************************************/
  123.  
  124. static int All_Cone_Intersections(Object, Ray, Depth_Stack)
  125. OBJECT *Object;
  126. RAY *Ray;
  127. ISTACK *Depth_Stack;
  128. {
  129.   int Intersection_Found, cnt, i;
  130.   VECTOR IPoint;
  131.   CONE_INT I[4];
  132.  
  133.   Intersection_Found = FALSE;
  134.  
  135.   if ((cnt = intersect_cone(Ray, (CONE *)Object, I)) != 0)
  136.   {
  137.     for (i = 0; i < cnt; i++)
  138.     {
  139.       VEvaluateRay(IPoint, Ray->Initial, I[i].d, Ray->Direction);
  140.  
  141.       if (Point_In_Clip(IPoint, Object->Clip))
  142.       {
  143.         push_entry_i1(I[i].d,IPoint,Object,I[i].t,Depth_Stack);
  144.  
  145.         Intersection_Found = TRUE;
  146.       }
  147.     }
  148.   }
  149.  
  150.   return (Intersection_Found);
  151. }
  152.  
  153.  
  154.  
  155. /*****************************************************************************
  156. *
  157. * FUNCTION
  158. *
  159. *   intersect_cone
  160. *
  161. * INPUT
  162. *   
  163. * OUTPUT
  164. *   
  165. * RETURNS
  166. *   
  167. * AUTHOR
  168. *
  169. *   Alexander Enzmann
  170. *   
  171. * DESCRIPTION
  172. *
  173. *   -
  174. *
  175. * CHANGES
  176. *
  177. *   -
  178. *
  179. ******************************************************************************/
  180.  
  181. static int intersect_cone(Ray, Cone, Intersection)
  182. RAY *Ray;
  183. CONE *Cone;
  184. CONE_INT *Intersection;
  185. {
  186.   int i = 0;
  187.   DBL a, b, c, z, t1, t2, len;
  188.   DBL d;
  189.   VECTOR P, D;
  190.  
  191.   Increase_Counter(stats[Ray_Cone_Tests]);
  192.  
  193.   /* Transform the ray into the cones space */
  194.  
  195.   MInvTransPoint(P, Ray->Initial, Cone->Trans);
  196.   MInvTransDirection(D, Ray->Direction, Cone->Trans);
  197.  
  198.   VLength(len, D);
  199.   VInverseScaleEq(D, len);
  200.  
  201.   if (Test_Flag(Cone, CYLINDER_FLAG))
  202.   {
  203.     /* Solve intersections with a cylinder */
  204.  
  205.     a = D[X] * D[X] + D[Y] * D[Y];
  206.  
  207.     if (a > EPSILON)
  208.     {
  209.       b = P[X] * D[X] + P[Y] * D[Y];
  210.  
  211.       c = P[X] * P[X] + P[Y] * P[Y] - 1.0;
  212.  
  213.       d = b * b - a * c;
  214.  
  215.       if (d >= 0.0)
  216.       {
  217.         d = sqrt(d);
  218.  
  219.         t1 = (-b + d) / a;
  220.         t2 = (-b - d) / a;
  221.  
  222.         z = P[Z] + t1 * D[Z];
  223.  
  224.         if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0))
  225.         {
  226.           Intersection[i].d   = t1 / len;
  227.           Intersection[i++].t = SIDE_HIT;
  228.         }
  229.  
  230.         z = P[Z] + t2 * D[Z];
  231.  
  232.         if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0))
  233.         {
  234.           Intersection[i].d   = t2 / len;
  235.           Intersection[i++].t = SIDE_HIT;
  236.         }
  237.       }
  238.     }
  239.   }
  240.   else
  241.   {
  242.     /* Solve intersections with a cone */
  243.  
  244.     a = D[X] * D[X] + D[Y] * D[Y] - D[Z] * D[Z];
  245.  
  246.     b = D[X] * P[X] + D[Y] * P[Y] - D[Z] * P[Z];
  247.  
  248.     c = P[X] * P[X] + P[Y] * P[Y] - P[Z] * P[Z];
  249.  
  250.     if (fabs(a) < EPSILON)
  251.     {
  252.       if (fabs(b) > EPSILON)
  253.       {
  254.         /* One intersection */
  255.  
  256.         t1 = -0.5 * c / b;
  257.  
  258.         z = P[Z] + t1 * D[Z];
  259.  
  260.         if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
  261.         {
  262.           Intersection[i].d   = t1 / len;
  263.           Intersection[i++].t = SIDE_HIT;
  264.         }
  265.       }
  266.     }
  267.     else
  268.     {
  269.       /* Check hits against the side of the cone */
  270.  
  271.       d = b * b - a * c;
  272.  
  273.       if (d >= 0.0)
  274.       {
  275.         d = sqrt(d);
  276.  
  277.         t1 = (-b - d) / a;
  278.         t2 = (-b + d) / a;
  279.  
  280.         z = P[Z] + t1 * D[Z];
  281.  
  282.         if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
  283.         {
  284.           Intersection[i].d   = t1 / len;
  285.           Intersection[i++].t = SIDE_HIT;
  286.         }
  287.  
  288.         z = P[Z] + t2 * D[Z];
  289.  
  290.         if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
  291.         {
  292.           Intersection[i].d   = t2 / len;
  293.           Intersection[i++].t = SIDE_HIT;
  294.         }
  295.       }
  296.     }
  297.   }
  298.  
  299.   if (Test_Flag(Cone, CLOSED_FLAG) && (fabs(D[Z]) > EPSILON))
  300.   {
  301.     d = (1.0 - P[Z]) / D[Z];
  302.  
  303.     a = (P[X] + d * D[X]);
  304.  
  305.     b = (P[Y] + d * D[Y]);
  306.  
  307.     if (((Sqr(a) + Sqr(b)) <= 1.0) && (d > Cone_Tolerance) && (d < Max_Distance))
  308.     {
  309.       Intersection[i].d   = d / len;
  310.       Intersection[i++].t = CAP_HIT;
  311.     }
  312.  
  313.     d = (Cone->dist - P[Z]) / D[Z];
  314.  
  315.     a = (P[X] + d * D[X]);
  316.  
  317.     b = (P[Y] + d * D[Y]);
  318.  
  319.     if ((Sqr(a) + Sqr(b)) <= (Test_Flag(Cone, CYLINDER_FLAG) ? 1.0 : Sqr(Cone->dist))
  320.       && (d > Cone_Tolerance) && (d < Max_Distance))
  321.     {
  322.       Intersection[i].d   = d / len;
  323.       Intersection[i++].t = BASE_HIT;
  324.     }
  325.   }
  326.  
  327.   if (i)
  328.   {
  329.     Increase_Counter(stats[Ray_Cone_Tests_Succeeded]);
  330.   }
  331.  
  332.   return (i);
  333. }
  334.  
  335.  
  336.  
  337. /*****************************************************************************
  338. *
  339. * FUNCTION
  340. *
  341. *   Inside_Cone
  342. *
  343. * INPUT
  344. *   
  345. * OUTPUT
  346. *   
  347. * RETURNS
  348. *   
  349. * AUTHOR
  350. *
  351. *   Alexander Enzmann
  352. *   
  353. * DESCRIPTION
  354. *
  355. *   -
  356. *
  357. * CHANGES
  358. *
  359. *   -
  360. *
  361. ******************************************************************************/
  362.  
  363. static int Inside_Cone(IPoint, Object)
  364. VECTOR IPoint;
  365. OBJECT *Object;
  366. {
  367.   CONE *Cone = (CONE *)Object;
  368.   DBL w2, z2, offset = (Test_Flag(Cone, CLOSED_FLAG) ? -EPSILON : EPSILON);
  369.   VECTOR New_Point;
  370.  
  371.   /* Transform the point into the cones space */
  372.  
  373.   MInvTransPoint(New_Point, IPoint, Cone->Trans);
  374.  
  375.   /* Test to see if we are inside the cone */
  376.  
  377.   w2 = New_Point[X] * New_Point[X] + New_Point[Y] * New_Point[Y];
  378.  
  379.   if (Test_Flag(Cone, CYLINDER_FLAG))
  380.   {
  381.     /* Check to see if we are inside a cylinder */
  382.  
  383.     if ((w2 > 1.0 + offset) ||
  384.         (New_Point[Z] < 0.0 - offset) ||
  385.         (New_Point[Z] > 1.0 + offset))
  386.     {
  387.       return (Test_Flag(Cone, INVERTED_FLAG));
  388.     }
  389.     else
  390.     {
  391.       return (!Test_Flag(Cone, INVERTED_FLAG));
  392.     }
  393.   }
  394.   else
  395.   {
  396.     /* Check to see if we are inside a cone */
  397.  
  398.     z2 = New_Point[Z] * New_Point[Z];
  399.  
  400.     if ((w2 > z2 + offset) ||
  401.         (New_Point[Z] < Cone->dist - offset) ||
  402.         (New_Point[Z] > 1.0+offset))
  403.     {
  404.       return (Test_Flag(Cone, INVERTED_FLAG));
  405.     }
  406.     else
  407.     {
  408.       return (!Test_Flag(Cone, INVERTED_FLAG));
  409.     }
  410.   }
  411. }
  412.  
  413.  
  414.  
  415. /*****************************************************************************
  416. *
  417. * FUNCTION
  418. *
  419. *   Cone_Normal
  420. *
  421. * INPUT
  422. *
  423. * OUTPUT
  424. *
  425. * RETURNS
  426. *
  427. * AUTHOR
  428. *
  429. *   Alexander Enzmann
  430. *
  431. * DESCRIPTION
  432. *
  433. *   -
  434. *
  435. * CHANGES
  436. *
  437. *   -
  438. *
  439. ******************************************************************************/
  440.  
  441. static void Cone_Normal(Result, Object, Inter)
  442. OBJECT *Object;
  443. VECTOR Result;
  444. INTERSECTION *Inter;
  445. {
  446.   CONE *Cone = (CONE *)Object;
  447.  
  448.   /* Transform the point into the cones space */
  449.  
  450.   MInvTransPoint(Result, Inter->IPoint, Cone->Trans);
  451.  
  452.   /* Calculating the normal is real simple in canonical cone space */
  453.  
  454.   switch (Inter->i1)
  455.   {
  456.     case SIDE_HIT:
  457.  
  458.       if (Test_Flag(Cone, CYLINDER_FLAG))
  459.       {
  460.         Result[Z] = 0.0;
  461.       }
  462.       else
  463.       {
  464.         Result[Z] = -Result[Z];
  465.       }
  466.  
  467.       break;
  468.  
  469.     case BASE_HIT:
  470.  
  471.       Make_Vector(Result, 0.0, 0.0, -1.0)
  472.  
  473.       break;
  474.  
  475.     case CAP_HIT:
  476.  
  477.       Make_Vector(Result, 0.0, 0.0, 1.0)
  478.  
  479.       break;
  480.   }
  481.  
  482.   /* Transform the point out of the cones space */
  483.  
  484.   MTransNormal(Result, Result, Cone->Trans);
  485.  
  486.   VNormalize(Result, Result);
  487. }
  488.  
  489.  
  490.  
  491. /*****************************************************************************
  492. *
  493. * FUNCTION
  494. *
  495. *   Translate_Cone
  496. *
  497. * INPUT
  498. *
  499. * OUTPUT
  500. *
  501. * RETURNS
  502. *
  503. * AUTHOR
  504. *
  505. *   Alexander Enzmann
  506. *
  507. * DESCRIPTION
  508. *
  509. *   -
  510. *
  511. * CHANGES
  512. *
  513. *   -
  514. *
  515. ******************************************************************************/
  516.  
  517. static void Translate_Cone(Object, Vector, Trans)
  518. OBJECT *Object;
  519. VECTOR Vector;
  520. TRANSFORM *Trans;
  521. {
  522.   Transform_Cone(Object, Trans);
  523. }
  524.  
  525.  
  526.  
  527. /*****************************************************************************
  528. *
  529. * FUNCTION
  530. *
  531. *   Rotate_Cone
  532. *
  533. * INPUT
  534. *
  535. * OUTPUT
  536. *
  537. * RETURNS
  538. *
  539. * AUTHOR
  540. *
  541. *   Alexander Enzmann
  542. *
  543. * DESCRIPTION
  544. *
  545. *   -
  546. *
  547. * CHANGES
  548. *
  549. *   -
  550. *
  551. ******************************************************************************/
  552.  
  553. static void Rotate_Cone(Object, Vector, Trans)
  554. OBJECT *Object;
  555. VECTOR Vector;
  556. TRANSFORM *Trans;
  557. {
  558.   Transform_Cone(Object, Trans);
  559. }
  560.  
  561.  
  562.  
  563. /*****************************************************************************
  564. *
  565. * FUNCTION
  566. *
  567. *   Scale_Cone
  568. *
  569. * INPUT
  570. *
  571. * OUTPUT
  572. *
  573. * RETURNS
  574. *
  575. * AUTHOR
  576. *
  577. *   Alexander Enzmann
  578. *
  579. * DESCRIPTION
  580. *
  581. *   -
  582. *
  583. * CHANGES
  584. *
  585. *   -
  586. *
  587. ******************************************************************************/
  588.  
  589. static void Scale_Cone(Object, Vector, Trans)
  590. OBJECT *Object;
  591. VECTOR Vector;
  592. TRANSFORM *Trans;
  593. {
  594.   Transform_Cone(Object, Trans);
  595. }
  596.  
  597.  
  598.  
  599. /*****************************************************************************
  600. *
  601. * FUNCTION
  602. *
  603. *   Transform_Cone
  604. *
  605. * INPUT
  606. *
  607. * OUTPUT
  608. *
  609. * RETURNS
  610. *
  611. * AUTHOR
  612. *
  613. *   Alexander Enzmann
  614. *
  615. * DESCRIPTION
  616. *
  617. *   -
  618. *
  619. * CHANGES
  620. *
  621. *   -
  622. *
  623. ******************************************************************************/
  624.  
  625. static void Transform_Cone(Object, Trans)
  626. OBJECT *Object;
  627. TRANSFORM *Trans;
  628. {
  629.   CONE *Cone = (CONE *)Object;
  630.  
  631.   Compose_Transforms(Cone->Trans, Trans);
  632.  
  633.   Compute_Cone_BBox(Cone);
  634. }
  635.  
  636.  
  637.  
  638. /*****************************************************************************
  639. *
  640. * FUNCTION
  641. *
  642. *   Invert_Cone
  643. *
  644. * INPUT
  645. *
  646. * OUTPUT
  647. *
  648. * RETURNS
  649. *
  650. * AUTHOR
  651. *
  652. *   Alexander Enzmann
  653. *
  654. * DESCRIPTION
  655. *
  656. *   -
  657. *
  658. * CHANGES
  659. *
  660. *   -
  661. *
  662. ******************************************************************************/
  663.  
  664. static void Invert_Cone(Object)
  665. OBJECT *Object;
  666. {
  667.   Invert_Flag(Object, INVERTED_FLAG);
  668. }
  669.  
  670.  
  671.  
  672. /*****************************************************************************
  673. *
  674. * FUNCTION
  675. *
  676. *   Create_Cone
  677. *
  678. * INPUT
  679. *
  680. * OUTPUT
  681. *
  682. * RETURNS
  683. *
  684. * AUTHOR
  685. *
  686. *   Alexander Enzmann
  687. *
  688. * DESCRIPTION
  689. *
  690. *   -
  691. *
  692. * CHANGES
  693. *
  694. *   -
  695. *
  696. ******************************************************************************/
  697.  
  698. CONE *Create_Cone()
  699. {
  700.   CONE *New;
  701.  
  702.   New = (CONE *)POV_MALLOC(sizeof(CONE), "cone");
  703.  
  704.   INIT_OBJECT_FIELDS(New, CONE_OBJECT, &Cone_Methods)
  705.  
  706.   Make_Vector(New->apex, 0.0, 0.0, 1.0);
  707.   Make_Vector(New->base, 0.0, 0.0, 0.0);
  708.  
  709.   New->apex_radius = 1.0;
  710.   New->base_radius = 0.0;
  711.  
  712.   New->dist = 0.0;
  713.  
  714.   New->Trans = Create_Transform();
  715.  
  716.   /* Cone/Cylinder has capped ends by default. */
  717.  
  718.   Set_Flag(New, CLOSED_FLAG);
  719.  
  720.   /* Default bounds */
  721.  
  722.   Make_BBox(New->BBox, -1.0, -1.0, 0.0, 2.0, 2.0, 1.0);
  723.  
  724.   return (New);
  725. }
  726.  
  727.  
  728.  
  729. /*****************************************************************************
  730. *
  731. * FUNCTION
  732. *
  733. *   Copy_Cone
  734. *
  735. * INPUT
  736. *
  737. * OUTPUT
  738. *
  739. * RETURNS
  740. *
  741. * AUTHOR
  742. *
  743. *   Alexander Enzmann
  744. *
  745. * DESCRIPTION
  746. *
  747. *   -
  748. *
  749. * CHANGES
  750. *
  751. *   -
  752. *
  753. ******************************************************************************/
  754.  
  755. static void *Copy_Cone(Object)
  756. OBJECT *Object;
  757. {
  758.   CONE *New;
  759.  
  760.   New = Create_Cone();
  761.  
  762.   /* Get rid of the transformation created in Create_Cone(). */
  763.  
  764.   Destroy_Transform(New->Trans);
  765.  
  766.   /* Copy cone. */
  767.  
  768.   *New = *((CONE *)Object);
  769.  
  770.   New->Trans = Copy_Transform(((CONE *)Object)->Trans);
  771.  
  772.   return (New);
  773. }
  774.  
  775.  
  776.  
  777. /*****************************************************************************
  778. *
  779. * FUNCTION
  780. *
  781. *   Create_Cylinder
  782. *
  783. * INPUT
  784. *
  785. * OUTPUT
  786. *
  787. * RETURNS
  788. *
  789. * AUTHOR
  790. *
  791. *   Alexander Enzmann
  792. *
  793. * DESCRIPTION
  794. *
  795. *   -
  796. *
  797. * CHANGES
  798. *
  799. *   -
  800. *
  801. ******************************************************************************/
  802.  
  803. CONE *Create_Cylinder()
  804. {
  805.   CONE *New;
  806.  
  807.   New = (CONE *)POV_MALLOC(sizeof(CONE), "cone");
  808.  
  809.   INIT_OBJECT_FIELDS(New, CONE_OBJECT, &Cone_Methods)
  810.  
  811.   Make_Vector(New->apex, 0.0, 0.0, 1.0);
  812.   Make_Vector(New->base, 0.0, 0.0, 0.0);
  813.  
  814.   New->apex_radius = 1.0;
  815.   New->base_radius = 1.0;
  816.   New->dist        = 0.0;
  817.  
  818.   New->Trans = Create_Transform();
  819.  
  820.   Set_Flag(New, CYLINDER_FLAG); /* This is a cylinder. */
  821.   Set_Flag(New, CLOSED_FLAG);   /* Has capped ends.    */
  822.  
  823.   /* Default bounds */
  824.  
  825.   Make_BBox(New->BBox, -1.0, -1.0, 0.0, 2.0, 2.0, 1.0);
  826.  
  827.   return (New);
  828. }
  829.  
  830.  
  831.  
  832. /*****************************************************************************
  833. *
  834. * FUNCTION
  835. *
  836. *   Compute_Cone_Data
  837. *
  838. * INPUT
  839. *
  840. * OUTPUT
  841. *
  842. * RETURNS
  843. *
  844. * AUTHOR
  845. *
  846. *   Alexander Enzmann
  847. *
  848. * DESCRIPTION
  849. *
  850. *   -
  851. *
  852. * CHANGES
  853. *
  854. *   Feb 1996: check for equal sized ends (cylinder) first [AED]
  855. *
  856. ******************************************************************************/
  857.  
  858. void Compute_Cone_Data(Object)
  859. OBJECT *Object;
  860. {
  861.   DBL tlen, len, tmpf;
  862.   VECTOR tmpv, axis, origin;
  863.   CONE *Cone = (CONE *)Object;
  864.  
  865.   /* Process the primitive specific information */
  866.  
  867.   if (fabs(Cone->apex_radius - Cone->base_radius) < EPSILON)
  868.   {
  869.     /* What we are dealing with here is really a cylinder */
  870.  
  871.     Set_Flag(Cone, CYLINDER_FLAG);
  872.  
  873.     Compute_Cylinder_Data(Object);
  874.  
  875.     return;
  876.   }
  877.  
  878.   if (Cone->apex_radius < Cone->base_radius)
  879.   {
  880.     /* Want the bigger end at the top */
  881.  
  882.     Assign_Vector(tmpv,Cone->base);
  883.     Assign_Vector(Cone->base,Cone->apex);
  884.     Assign_Vector(Cone->apex,tmpv);
  885.  
  886.     tmpf = Cone->base_radius;
  887.     Cone->base_radius = Cone->apex_radius;
  888.     Cone->apex_radius = tmpf;
  889.   }
  890.  
  891.   /* Find the axis and axis length */
  892.  
  893.   VSub(axis, Cone->apex, Cone->base);
  894.  
  895.   VLength(len, axis);
  896.  
  897.   if (len < EPSILON)
  898.   {
  899.     Error("Degenerate cone/cylinder.\n");
  900.   }
  901.   else
  902.   {
  903.     VInverseScaleEq(axis, len)
  904.   }
  905.  
  906.   /* Determine alignment */
  907.  
  908.   tmpf = Cone->base_radius * len / (Cone->apex_radius - Cone->base_radius);
  909.  
  910.   VScale(origin, axis, tmpf);
  911.  
  912.   VSub(origin, Cone->base, origin);
  913.  
  914.   tlen = tmpf + len;
  915.  
  916.   Cone->dist = tmpf / tlen;
  917.  
  918.   Compute_Coordinate_Transform(Cone->Trans, origin, axis, Cone->apex_radius, tlen);
  919.  
  920.   /* Recalculate the bounds */
  921.  
  922.   Compute_Cone_BBox(Cone);
  923. }
  924.  
  925.  
  926.  
  927. /*****************************************************************************
  928. *
  929. * FUNCTION
  930. *
  931. *   Compute_Cylinder_Data
  932. *
  933. * INPUT
  934. *
  935. * OUTPUT
  936. *
  937. * RETURNS
  938. *
  939. * AUTHOR
  940. *
  941. *   Alexander Enzmann
  942. *
  943. * DESCRIPTION
  944. *
  945. *   -
  946. *
  947. * CHANGES
  948. *
  949. *   -
  950. *
  951. ******************************************************************************/
  952.  
  953. void Compute_Cylinder_Data(Object)
  954. OBJECT *Object;
  955. {
  956.   DBL tmpf;
  957.   VECTOR axis;
  958.   CONE *Cone = (CONE *)Object;
  959.  
  960.   VSub(axis, Cone->apex, Cone->base);
  961.  
  962.   VLength(tmpf, axis);
  963.  
  964.   if (tmpf < EPSILON)
  965.   {
  966.     Error("Degenerate cylinder, base point = apex point.\n");
  967.   }
  968.   else
  969.   {
  970.     VInverseScaleEq(axis, tmpf)
  971.  
  972.     Compute_Coordinate_Transform(Cone->Trans, Cone->base, axis, Cone->apex_radius, tmpf);
  973.   }
  974.  
  975.   Cone->dist = 0.0;
  976.  
  977.   /* Recalculate the bounds */
  978.  
  979.   Compute_Cone_BBox(Cone);
  980. }
  981.  
  982.  
  983.  
  984.  
  985. /*****************************************************************************
  986. *
  987. * FUNCTION
  988. *
  989. *   Destroy_Cone
  990. *
  991. * INPUT
  992. *
  993. * OUTPUT
  994. *
  995. * RETURNS
  996. *
  997. * AUTHOR
  998. *
  999. *   Alexander Enzmann
  1000. *
  1001. * DESCRIPTION
  1002. *
  1003. *   -
  1004. *
  1005. * CHANGES
  1006. *
  1007. *   -
  1008. *
  1009. ******************************************************************************/
  1010.  
  1011. static void Destroy_Cone(Object)
  1012. OBJECT *Object;
  1013. {
  1014.   Destroy_Transform(((CONE *)Object)->Trans);
  1015.  
  1016.   POV_FREE (Object);
  1017. }
  1018.  
  1019.  
  1020.  
  1021. /*****************************************************************************
  1022. *
  1023. * FUNCTION
  1024. *
  1025. *   Compute_Cone_BBox
  1026. *
  1027. * INPUT
  1028. *
  1029. *   Cone - Cone/Cylinder
  1030. *
  1031. * OUTPUT
  1032. *
  1033. *   Cone
  1034. *
  1035. * RETURNS
  1036. *
  1037. * AUTHOR
  1038. *
  1039. *   Dieter Bayer
  1040. *
  1041. * DESCRIPTION
  1042. *
  1043. *   Calculate the bounding box of a cone or cylinder.
  1044. *
  1045. * CHANGES
  1046. *
  1047. *   Aug 1994 : Creation.
  1048. *
  1049. ******************************************************************************/
  1050.  
  1051. void Compute_Cone_BBox(Cone)
  1052. CONE *Cone;
  1053. {
  1054.   Make_BBox(Cone->BBox, -1.0, -1.0, 0.0, 2.0, 2.0, 1.0);
  1055.  
  1056.   Recompute_BBox(&Cone->BBox, Cone->Trans);
  1057. }
  1058.  
  1059.